// SeqList.hpp
// Author: Paddy Huang
// Date: 2020.03.04 21:23

#ifndef SEQ_LIST_HXX
#define SEQ_LIST_HXX

#include <iostream>
using namespace std;

#define MAXSIZE 10000
#define ERROR -1
// #define DataType int

template<class T>
class Node{
	public:
		T data;
};

template<class T>
class SeqList{
	public:
		SeqList();  // Constructor
        ~SeqList(); // Destructor
        void CreateSeqList(int number);
        const void TraverseSeqList() noexcept;
        const bool isEmpty() noexcept;
        const bool isFull() noexcept;
        const int GetLength() noexcept;
        int GetElemByElem(T data);
        Node<T> GetElemByIndex(int i);
        void InsertSeqList(int index, T data);
        void InsertSeqListAtHead(T data);
        void InsertSeqListAtRear(T data);
        void DeleteElem(int index);
        void DeleteElemByELem(T data);
        void DeleteAll();
        void DeleteAtHead();
	private:
		Node<T> *element;
		int length;
};

template<class T>
SeqList<T>::SeqList(){
	element = new Node<T>[MAXSIZE];
	if(!element) exit(ERROR);
	length = 0;
}

template<class T>
SeqList<T>::~SeqList(){
	delete element;
	element = NULL;
	length = 0;
}

template<class T>
void SeqList<T>::CreateSeqList(int number){
	if(number < 0){
		cout << "Inputted number for SeqList erorr" << endl;
		exit(ERROR);
	}
	for(int i = 0; i < number; i++){
		cout << "Inputting Element No." << i + 1;
		cin >> element[i].data;
	}
	length = number;
}

template<class T>
const void SeqList<T>::TraverseSeqList() noexcept{
	for(int i = 0; i < length; i++) 
		cout << "Element No." << i + 1 << " : " << element[i].data << endl;
}

template<class T>
const bool SeqList<T>::isEmpty() noexcept{
    return length <= 0;
}

template<class T>
const bool SeqList<T>::isFull() noexcept{
    return length >= MAXSIZE;
}

template<class T>
const int SeqList<T>::GetLength() noexcept{
    return length;
}

template<class T>
int SeqList<T>::GetElemByElem(T data){
	int index = 0;
	while(index < length && element[index].data != data) 
        index++;
	if(index >= 0 && index < length) 
        return index + 1;
	return ERROR;
}

template<class T>
Node<T> SeqList<T>::GetElemByIndex(int index){
	if(index < 1 || index > length) 
        cout << "Index not exists" << endl;
	return element[index - 1];
}

template<class T>
void SeqList<T>::InsertSeqList(int index, T data){
	if(index < 1 || index > length + 1) 
        cout << "Invalid index" << endl;
	else if(length >= MAXSIZE) 
        cout << "List is full" << endl;
	else{
		for(int i = length; i >= index - 1; i--) 
            element[i] = element[i - 1];
		element[index - 1].data = data;
		length++;
	}
}

template<class T>
void SeqList<T>::InsertSeqListAtHead(T data){
	if(length >=  MAXSIZE) 
        cout << "List is full" << endl;
	else{
		for(int i = length; i >= 0; i--) 
            element[i] = element[i - 1];
		element[0].data = data;
		length++;
	}
} 

template<class T>
void SeqList<T>::InsertSeqListAtRear(T data){
	if(length >=  MAXSIZE) 
        cout << "List is full" << endl;
	else{
		element[length].data = data;
		length++;
	}
}

template<class T>
void SeqList<T>::DeleteElem(int index){
	if(index < 1 || index > length) 
        cout << "Invalid index" << endl;
	else{
		for(int i = index; i < length; i++) 
            element[i - 1] = element[i];
		length--;
	}
}

template<class T>
void SeqList<T>::DeleteElemByELem(T data){
	int index = 0;
	while(index < length && element[index].data != data) 
        index++;
	for(int i = index; i < length; i++) 
        element[i- 1] = element[i];
	length--;
}

template<class T>
void SeqList<T>::DeleteAll(){
	for(int i = 0; i < length; i++) 
        element[i].data = 0;
	length = 0;
}

template<class T>
void SeqList<T>::DeleteAtHead(){
	for(int i = 1; i < length; i++) 
        element[i - 1] = element[i];
	length--;
}

#endif
